package com.framework.auth.handler;

import com.alibaba.fastjson.JSON;

import com.framework.auth.domain.AuthUserReq;
import com.framework.authorization.vo.UserDetailsVo;
import com.framework.common.Enums.FrameworkErrorCodeEnum;
import com.framework.common.Enums.LoginTypeEnum;
import com.framework.common.Enums.UserTypeEnum;
import com.framework.common.exception.BusinessException;
import com.framework.core.api.feign.RemoteApiService;
import com.framework.core.api.feign.RemoteThirdUserService;
import com.framework.core.api.feign.RemoteWeixinService;
import com.framework.core.api.request.ThirdUserInfoReq;
import com.framework.core.api.response.ThirdUserInfoQueryRes;
import com.framework.core.api.response.WxUserOpenIdRes;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 微信登录认证模式
 * @author zhoubb
 * @version V1.0
 * @Date 2020/4/12 16:19
 * @since JDK 1.8
 */
@Component
@Slf4j
@Api(value = "RestAuthenticationHandler", description = "认证授权接口")
public class RestAuthenticationHandler implements AuthenticationProvider  {

    @Value("${spring.profiles.active}")
    private String profiles;

    @Autowired
    private RemoteWeixinService remoteWeixinService;

    @Autowired
    private RemoteApiService remoteApiService;

    @Autowired
    private RemoteThirdUserService remoteThirdUserService;

    @Override
    @ApiOperation(value = "团团钻用户授权", httpMethod = "POST")
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        long start = System.currentTimeMillis();
        if(authentication == null) {
            log.error("认证信息为空!");
            throw new UsernameNotFoundException("认证信息为空!");
        }

        String openid = null;
        String unionId = null;
        String sessionKey = null;
        String authName = authentication.getName();
        if(StringUtils.isBlank(authName)) {
            log.error("用户名信息为空!");
            throw new UsernameNotFoundException("用户名信息为空!");
        }
        AuthUserReq authUserReq = JSON.parseObject(authName, AuthUserReq.class);
        log.info("接收到认证请求-[{}]", JSON.toJSONString(authUserReq));
        Authentication info = null;
        Integer userId = null;

        String loginCode = authUserReq.getCode();
        String loginType = authUserReq.getLoginType(); // 登录类型

        if (StringUtils.equals(LoginTypeEnum.WECHAT.getValue(), loginType)) {
            //微信小程序登录
            log.info("开始微信用户认证，用户code=[{}]", authUserReq.getCode());
            //根据code获取openId
            WxUserOpenIdRes wxUserInfoRes = remoteWeixinService.getWeixinOpenidAndKey(loginCode);
            if(wxUserInfoRes == null) {
                log.warn("[用户认证]-[获取微信用户失败]-返回结果为空");
                throw new UsernameNotFoundException("获取用户微信信息失败!");
            }
            log.info("[用户认证]-[调用接口获取微信用户成功]-返回结果=[{}]", JSON.toJSONString(wxUserInfoRes));
            openid =  wxUserInfoRes.getOpenid();
            sessionKey = wxUserInfoRes.getSession_key();
            unionId = wxUserInfoRes.getUnionid();
            if(StringUtils.isBlank(openid) || StringUtils.isBlank(sessionKey)) {
                log.warn("[用户认证]-[微信用户信息为空]");
                throw new DisabledException(openid);
            }
            if(StringUtils.equals("dev", profiles)) {
                openid = "oGc-A4qbP1kLxtzWBqIrfIozh9gw";
                //openid = "oGc-A4koUMF0ACd61SaKKjBbzdgE";
            }

            // 查询并且注册第三方平台用户信息和用户登录主表信息
            ThirdUserInfoReq thirdUserInfoReq = new ThirdUserInfoReq();
            BeanUtils.copyProperties(authUserReq, thirdUserInfoReq);
            thirdUserInfoReq.setCityId(authUserReq.getCity());
            thirdUserInfoReq.setOpenId(openid);
            thirdUserInfoReq.setUnionId(unionId);
            thirdUserInfoReq.setGender(authUserReq.getGender());
            ThirdUserInfoQueryRes thirdUserInfo = remoteThirdUserService.getOrRegThirdUserInfoByOpenId(thirdUserInfoReq);
            if(thirdUserInfo == null || !StringUtils.equals(FrameworkErrorCodeEnum.SUCCESS.getCode(), thirdUserInfo.getCode())) {
                log.warn("[用户认证]-[微信用户信息查询失败]-[{}]", thirdUserInfo == null? "网络问题":thirdUserInfo.getMsg());
                if(StringUtils.equals(FrameworkErrorCodeEnum.USER_NOT_EXITS.getCode(), thirdUserInfo.getCode())) {
                    throw new BusinessException(FrameworkErrorCodeEnum.USER_NOT_EXITS);
                }
                throw new DisabledException(openid);
            }
            List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(1);
            authorities.add(new SimpleGrantedAuthority(UserTypeEnum.getCode(Integer.valueOf(thirdUserInfo.getUserType()))));
            //UserDetails userDetails = new UserTtzDetailsVo(thirdUserInfo.getOldUserId(), thirdUserInfo.getOpenId(), authorities);
            UserDetails userDetails = new UserDetailsVo(thirdUserInfo.getUserId().toString(), thirdUserInfo.getOpenId(), authorities);
            Authentication authInfo = new UsernamePasswordAuthenticationToken(userDetails, openid, authorities);
            log.info("[微信用户认证结束]-[微信小程序登录]-用户名=[{}]", thirdUserInfo.getOpenId());
            return authInfo;
        } else if(StringUtils.equals(LoginTypeEnum.ACCOUNT.getValue(), loginType)) {
            // 账号密码登录
            String password = (String) authentication.getCredentials();
        } else {
            // 短信验证码登录
        }

        return null;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        //return aClass.equals(UsernamePasswordAuthenticationToken.class);
        return true;
    }
}